package cn.faster.sys.service;

import cn.faster.common.constants.Constants;
import cn.faster.common.exception.CaptchaException;
import cn.faster.common.exception.CaptchaExpireException;
import cn.faster.common.utils.sys.StringUtils;
import cn.faster.common.utils.sys.redis.RedisCacheUtils;
import cn.faster.config.security.jwt.JwtUtils;
import cn.faster.sys.config.SpringFrameworkConfig;
import cn.faster.sys.entity.SysUser;
import lombok.AllArgsConstructor;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.security.auth.login.FailedLoginException;

/**
 * @program: faster-framework
 * @description: 登录Service层 todo token的生产和 code验证码的校验
 * @author: 暴力袋鼠哥
 * @create: 2021-11-24 21:40
 **/
@Service
@AllArgsConstructor
public class SysLoginService {

    private final TokenService tokenService;

    //private final StringRedisTemplate redisCache;
    private final RedisCacheUtils redisCacheUtils;

    private final SpringFrameworkConfig springFrameworkConfig;

    /**
     * 检验登录
     *
     * @param username
     * @param password
     * @param code
     * @param uuid
     * @return 检验结果
     */
    public String login(String username, String password, String code, String uuid) throws Exception {
        String flag = springFrameworkConfig.getIgnoreCode();
        if (!Boolean.getBoolean(flag)) {
            // 判断验证码的正确性
            verificationCode(code, uuid);
        }
        // 检验账号密码
        shiroLogin(username, password);
        // 生产token
        SysUser principal = (SysUser) SecurityUtils.getSubject().getPrincipal();
        return JwtUtils.sign(username, principal.getSalt(), Constants.JWT_EXPIRE_TIME);
    }

    /**
     * 验证码校验
     *
     * @param code
     * @param uuid
     */
    public void verificationCode(String code, String uuid) {
        String capKey = Constants.CAPTCHA_CODE_KEY + uuid;
        String cap = redisCacheUtils.getCacheObject(capKey);
        // 验证码失效
        if (StringUtils.isEmpty(cap)) throw new CaptchaExpireException();
        // 验证码错误
        if (!code.equals(cap)) throw new CaptchaException();
        // 清楚验证码缓存
        redisCacheUtils.deleteObject(capKey);
    }

    /**
     * 登录操作
     *
     * @param username
     * @param password
     */
    public void shiroLogin(String username, String password) throws FailedLoginException {
        // 登录令牌验证
        if (username.isEmpty() || password.isEmpty()) {
            throw new FailedLoginException("账号密码不能为空！");
        }
        SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password, false));
    }
}
